package resources;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.newdawn.slick.Animation;
import org.newdawn.slick.Image;
import org.newdawn.slick.Sound;
import org.newdawn.slick.UnicodeFont;
import org.newdawn.slick.loading.LoadingList;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class ResourceManager implements IResourceManager {
	
	private static final String PATH_ATTRIBUTE_TAG = "path";

	private static final String DESCRIPTION_ATTRIBUTE__TAG = "description";

	private static final String ID_ATTRIBUTE_TAG = "id";

	private static final String RESOURCE_FILE_IMAGE_TAG = "image";

	private static Logger _tracer = Logger.getLogger(ResourceManager.class.getName());
	
	private int _resourceManagerId;
	private Map<Integer, Sound> 	  _soundMap;
	private Map<Integer, Image> 	  _imageMap;
	private Map<Integer, String> 	  _textMap;
	private Map<Integer, UnicodeFont> _fontsMap;
	
	public ResourceManager(int resourceManagerId){
		_tracer.info("Creating a new resource manager " + resourceManagerId);
		
		_resourceManagerId = resourceManagerId;
		
		_soundMap = new HashMap<Integer, Sound>();
		_imageMap = new HashMap<Integer, Image>();
		_textMap  = new HashMap<Integer, String>();
		_fontsMap = new HashMap<Integer, UnicodeFont>();
		
		_tracer.info("Created a resource manager " + resourceManagerId);
	}

	@Override
	public Sound getSound(int resourceId) {
		return _soundMap.get(resourceId);
	}
	
	@Override
	public Animation getAnimation(int resourceId) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Image getImage(int resourceId) {
		return _imageMap.get(resourceId);
	}

	@Override
	public UnicodeFont getFont(int resourceId) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getText(int resourceId) {
		return null;
	}

	public int getResourceCount() {
		return _soundMap.size() + _imageMap.size() + _textMap.size() + _fontsMap.size();
	}

	@Override
	public void loadResources(InputStream is) throws ResourceException{
		// TODO Auto-generated method stub
	}

	@Override
	public int getId() {
		return _resourceManagerId;
	}
	
	public Image loadImage(int id, String path, String description) throws ResourceException {
		if(path == null )
			throw new ResourceException("Image resource [" + id + "] has invalid path");
		
		Image image = null;
		try{
			image = new Image( ResourceManager.class.getResourceAsStream(path), path, false );
			image.setName(description);
		} catch (Throwable t) {
			throw new ResourceException("Could not load image", t);
		}
		
		if ( _imageMap.containsKey(id) ){
			throw new ResourceException("Id already exists : " +id );
		}
		
		_imageMap.put(id, image);
		
		return image;
	}
	

	public Sound loadSound(int id, String path) throws ResourceException {
		if(path == null || path.length() == 0)
			throw new ResourceException("Sound resource [" + id + "] has invalid path");
		
		Sound sound = null;
		try {
			sound = new Sound(path);
		} catch (Throwable t) {
			throw new ResourceException("Could not load sound", t);
		}
		
		if(_soundMap.containsKey(id)){
			throw new ResourceException("Id already exists : " + id );
		}
		
		_soundMap.put(id, sound);
		
		return sound;
	}

	
	public void loadResources(InputStream is, boolean deferred) throws Exception {
		DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
		
		Document doc = docBuilder.parse (is);
		
		// normalize text representation
        doc.getDocumentElement ().normalize ();
        
        if(deferred){
        	LoadingList.setDeferredLoading(true);
        }
        
        // generate all simple images
        addAllImagesFromResourceFile( doc );
//        NodeList listResources = doc.getElementsByTagName("resource");
//        
//        int totalResources = listResources.getLength();
//        
//        if(deferred){
//        	LoadingList.setDeferredLoading(true);
//        }
//        	
//        for(int resourceIdx = 0; resourceIdx < totalResources; resourceIdx++){
//        	
//        	Node resourceNode = listResources.item(resourceIdx);
//        	
//        	if(resourceNode.getNodeType() == Node.ELEMENT_NODE){
//        		Element resourceElement = (Element)resourceNode;
//        		
//        		String type = resourceElement.getAttribute("type");
//        		
//        		if(type.equals("image")){
//        			loadImage(Integer.getInteger( resourceElement.getAttribute("id") ), resourceElement.getTextContent());
//        		}else if(type.equals("spritesheet")){
//        			//addElementAsSpriteSheet(resourceElement);
//        		}else if(type.equals("sound")){
//        			//addElementAsSound(resourceElement);
//        		}else if(type.equals("text")){
//        			//addElementAsText(resourceElement);
//        		}else if(type.equals("font")){
//        			//addElementAsFont(resourceElement);
//        		}else if(type.equals("animation")){
//        			//addElementAsAnimation(resourceElement);
//        		}
//        	}
//        }

	}

	private void addAllImagesFromResourceFile(Document doc) throws ResourceException {
		NodeList listResources = doc.getElementsByTagName(RESOURCE_FILE_IMAGE_TAG);
		
		int totalImages = listResources.getLength();
		
		for(int imageIdx = 0; imageIdx < totalImages; imageIdx++){
			
			Node resourceNode = listResources.item(imageIdx);
        	
        	if(resourceNode.getNodeType() == Node.ELEMENT_NODE){
        		Element resourceElement = (Element)resourceNode;
			
        		String  description = null;
        		String  path		= null;
        		Integer id  		= null;
        	
        		try {
        			
        			description = resourceElement.getAttribute(DESCRIPTION_ATTRIBUTE__TAG);
        			path 		= resourceElement.getAttribute(PATH_ATTRIBUTE_TAG);
        			id 	 		= Integer.valueOf( resourceElement.getAttribute(ID_ATTRIBUTE_TAG) );
        		
					loadImage( id, path,description );
					
        		} catch (ResourceException e) {
					_tracer.severe("Could not load resource Image [#" + imageIdx + "] Named [" + description + "]");
					throw e;
				} catch(Throwable t){
					String msg = "Could not parse resource Image [#" + imageIdx + "] resource [" + resourceNode + "]";
					_tracer.severe(msg);
					
					throw new ResourceException(msg, t);
				}
				
        	}
		}
	}
}
